package org.nlp2rdf.navigator.benchmark;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.log4j.Logger;
import org.dllearner.utilities.Files;
import org.dllearner.utilities.JamonMonitorLogger;
import org.dllearner.utilities.experiments.ExperimentConfiguration;
import org.dllearner.utilities.experiments.Table;
import org.nlp2rdf.navigator.api.KnowledgeBase;
import org.nlp2rdf.navigator.client.common.ClassificationResultDTO;
import org.nlp2rdf.navigator.client.common.ExampleDTO;
import org.nlp2rdf.navigator.client.common.SearchResultDTO;
import org.nlp2rdf.navigator.component.ComponentConfig;
import org.nlp2rdf.navigator.server.WorkerServletWrapper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jamonapi.MonKeyImp;

public class Execute extends ExperimentConfiguration {
	private static final Logger logger = Logger.getLogger(Execute.class);

	// private static Logger logger = LoggerFactory.getLogger(Execute.class);

	public static MonKeyImp logFMeasure = new MonKeyImp("F-Measure", JamonMonitorLogger.PERCENTAGE);
	public static MonKeyImp logPrecision = new MonKeyImp("Precision", JamonMonitorLogger.PERCENTAGE);
	public static MonKeyImp logRecall = new MonKeyImp("Recall", JamonMonitorLogger.PERCENTAGE);

	static MonKeyImp instancesPerClass = new MonKeyImp("instancesPerClass", JamonMonitorLogger.COUNT);

	static List<MonKeyImp> mks = new ArrayList<MonKeyImp>(Arrays.asList(new MonKeyImp[] { logPrecision,
			logRecall, logFMeasure, instancesPerClass }));

	private static String resultFolder = "results/";


	static final String xmlPath = "org/nlp2rdf/navigator/xml/";
	static final String pathModifier = ComponentConfig.getRootPath() + "navigatorfiles/";

	static ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {
			xmlPath + "benchmark.xml", "navigator_dbpedia.xml" });

	//static KnowledgeBase mySession = KnowledgeBase.getInstance(context, "benchmark");
    static KnowledgeBase mySession = KnowledgeBase.getInstance(context, "dbpedia");

	static String[] negativesFix = new String[] { "http://dbpedia.org/resource/Alfonso_Arau",
			"http://dbpedia.org/resource/Alfonso_Cuar%C3%B3n",
			"http://dbpedia.org/resource/Arnold_Schwarzenegger__Arnold_StrongArnie",
			"http://dbpedia.org/resource/Amitabh_Bachchan", "http://dbpedia.org/resource/Ardal_O%27Hanlon",
			"http://dbpedia.org/resource/Anthony_Hopkins", "http://dbpedia.org/resource/Bille_August",
			"http://dbpedia.org/resource/Bill_Macy", "http://dbpedia.org/resource/Bill_Mumy",
			"http://dbpedia.org/resource/Bill_Bixby" };

	static String
	// categoryURI = "http://dbpedia.org/resource/Category:Flora_of_Spain";
	// categoryURI =
	// "http://dbpedia.org/resource/Category:Railway_stations_in_New_Zealand";all
	// categoryURI =
	// "http://dbpedia.org/resource/Category:Musicals_based_on_novels";
	categoryURIStatic = "http://dbpedia.org/ontology/Skyscraper";

	// categoryURIStatic = "http://dbpedia.org/ontology/VoiceActor";

	int noisePercentage;
	String ignoreProperty = null;

	public Execute(String label, int i) {
		super(label, i);
	}

	public static void main(String[] args) throws Exception {
		System.out.println("starting");
		Files.mkdir(resultFolder);
		doClasses();
//		doCategories();
		// Logger.getRootLogger().setLevel(Level.TRACE);

	}


	public static void doCategories() throws Exception {
		List<String> categories = getCategories();

		StringBuffer total = new StringBuffer("****************");
		
		int iterations = 4;
		int averageOver = 3 ; 
		Execute execute = new Execute("categories", iterations);
		execute.noisePercentage = 20;
		execute.ignoreProperty = "http://www.w3.org/2004/02/skos/core#subject";
		

		execute.init(mks);
		for (String categoryUri : categories) {

			SortedSet<String> pos = getPositivesCategory(categoryUri);
		
			logger.info("Positives: " + pos.size());
			execute.add(instancesPerClass, 0, pos.size());
			SortedSet<String> neg = getNegativesClass(pos, categoryUri, pos.size());
			logger.info("Negatives: " + neg.size());
			for (int i = 0; i < averageOver; i++) {
				LearnOne l = new LearnOne(mySession, execute);
				try {
					l.exampleSize = 10;
					l.doOneCategory(pos, neg);
				} catch (Exception e) {
					e.printStackTrace();
				}
				logger.info(l.log + "");
				total.append(l.log + "\n"+categoryUri+"**************\n");
			}

			Table expTable = new Table();
			expTable.addTableRowColumns(execute.getTableRows());
			expTable.write(resultFolder, execute.experimentName);

		}
		logger.info(total.toString());
		JamonMonitorLogger.writeHTMLReport("log/tiger.html");
	}

	public static void doClasses() throws Exception {
		List<String> classes = getClasses();
		StringBuffer total = new StringBuffer("****************");
		int iterations = 4;

		int averageOver = 3 ; 
		Execute execute = new Execute("classes", iterations);
		execute.noisePercentage = 0;

		execute.init(mks);
		for (String classUri : classes) {

			SortedSet<String> pos = getPositivesClass(classUri);
			logger.info("Positives: " + pos.size());
			execute.add(instancesPerClass, 0, pos.size());
			SortedSet<String> neg = getNegativesClass(pos,classUri, pos.size());
			logger.info("Negatives: " + neg.size());
			// all.append(doOneCategory(categoryURI, pos, neg));
			for (int i = 0; i < averageOver; i++) {
				LearnOne 	l = new LearnOne(mySession, execute);
				try {
					l.exampleSize = 10;
					l.doOneOntologyClass(classUri, pos, neg);
				} catch (Exception e) {
					e.printStackTrace();
					System.exit(0);
					
				}
				logger.info(l.log + "");
				total.append(l.log + "\n");

			}

			Table expTable = new Table();
			expTable.addTableRowColumns(execute.getTableRows());
			expTable.write(resultFolder, execute.experimentName);

		}
		logger.info(total.toString());
		JamonMonitorLogger.writeHTMLReport("log/tiger.html");
	}

	public static List<String> getClasses() {
		// List<String> l = new ArrayList<String>(Arrays.asList(new String[] {
		// "http://dbpedia.org/ontology/Skyscraper" }));
		try {
			List<String> l = Arrays.asList(Files.readFileAsArray(new File(pathModifier + "classlist.txt")));
			System.out.println(l);
			return l;

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static SortedSet<String> getNegativesClass(SortedSet<String> pos, String classUri, int size) throws Exception {
		SortedSet<String> neg = new TreeSet<String>();
		SearchResultDTO negatives = mySession.search("negativesRandom", classUri, size);
		for (ExampleDTO string : negatives.getMatching()) {
			neg.add(string.getUri());
		}
		neg.removeAll(pos);
		
		if (neg.size()==0){
			logger.info("not enough negatives found trying "+ 2*size);
			return getNegativesClass(pos, classUri, 2*size);
		}
		return neg;
	}

	public static SortedSet<String> getPositivesClass(String classUri) throws Exception {
		SortedSet<String> pos = new TreeSet<String>();
		ClassificationResultDTO cl = mySession.classify("\"" + classUri + "\"", 0, 0);
		for (ExampleDTO string : cl.getRetrievedExamples()) {
			pos.add(string.getUri());
		}
		logger.info("Positives: " + pos.size());
		return pos;
	}

	public static SortedSet<String> getPositivesCategory(String categoryUri) throws Exception {
		SortedSet<String> pos = new TreeSet<String>();

		SearchResultDTO positives = mySession.search("positives", categoryUri, 0);
		for (ExampleDTO string : positives.getMatching()) {
			pos.add(string.getUri());
		}
		logger.info("Positives: " + pos.size());
		return pos;
	}

	public static SortedSet<String> getNegativesCategory(String categoryUri, int size) throws Exception {
		SortedSet<String> neg = new TreeSet<String>(Arrays.asList(negativesFix));
		// SearchResultDTO negatives = mySession.search("negativesClass",
		// categoryUri, size);
		// for (ExampleDTO string : negatives.getMatching()) {
		// neg.add(string.getUri());
		// }
		return neg;
	}

	// public static void makeBenchmark() throws Exception{
	// List<String> categories = getCategories();
	// for (String categoryURI : categories) {
	// Set<String> pos = new HashSet<String>();
	// SearchResultDTO positives = mySession.search("positives", categoryURI,
	// 0);
	// for (ExampleDTO string : positives.getMatching()) {
	// pos.add(string.getUri());
	// }
	//			
	// Set<String> neg = new HashSet<String>();
	// SearchResultDTO negatives = mySession.search("negatives", categoryURI,
	// pos.size());
	// for (ExampleDTO string : negatives.getMatching()) {
	// neg.add(string.getUri());
	// }
	//			
	//			
	//
	// }
	// }


	public static List<String> getCategories() {
		try {
			List<String> l = Arrays.asList(Files.readFileAsArray(new File(pathModifier + "100er.txt")));
			logger.info(l);
			return l;

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

}
